• Steven Ponce
  • About
  • Data Visualizations
  • Projects
  • Resume
  • Email

On this page

  • Steps to Create this Graphic
    • 1. Load Packages & Setup
    • 2. Read in the Data
    • 3. Examine the Data
    • 4. Tidy Data
    • 5. Visualization Parameters
    • 6. Plot
    • 7. Save
    • 8. Session Info
    • 9. GitHub Repository

The Architecture of Global Country Codes

  • Show All Code
  • Hide All Code

  • View Source

Analysis of ISO country codes reveals geographic and alphabetic patterns in international standardization. Most nations maintain three distinct identifiers.

TidyTuesday
Data Visualization
R Programming
2024
Author

Steven Ponce

Published

November 9, 2024

Figure 1: A visualization titled ‘The Architecture of Global Country Codes’ showing an analysis of 249 ISO country codes by first letter and numeric value. Ridge plots in purple to orange show the distribution of country codes, with early alphabet countries having lower numeric codes and later alphabet countries having higher codes. A waffle chart in the top right indicates which countries maintain complete sets of Alpha-2, Alpha-3, and Numeric codes.

Steps to Create this Graphic

1. Load Packages & Setup

Show code
```{r}
#| label: load
#| warning: false

## 1. LOAD PACKAGES & SETUP ----
if (!require("pacman")) install.packages("pacman")
pacman::p_load(
  tidyverse, # Easily Install and Load the 'Tidyverse'
  ggtext, # Improved Text Rendering Support for 'ggplot2'
  showtext, # Using Fonts More Easily in R Graphs
  janitor, # Simple Tools for Examining and Cleaning Dirty Data
  scales, # Scale Functions for Visualization
  glue, # Interpreted String Literals
  here, # A Simpler Way to Find Your Files
  ggridges, # Ridgeline Plots in 'ggplot2'
  waffle, # Create Waffle Chart Visualizations
  patchwork # The Composer of Plots
)

### |- figure size ----
camcorder::gg_record(
  dir    = here::here("temp_plots"),
  device = "png",
  width  =  10,
  height =  12,
  units  = "in",
  dpi    = 320
)

### |- resolution ----
showtext_opts(dpi = 320, regular.wt = 300, bold.wt = 800)
```

2. Read in the Data

Show code
```{r}
#| label: read
#| include: true
#| eval: true
#| warning: false

tt <- tidytuesdayR::tt_load(2024, week = 46)

countries            <- tt$countries |> clean_names()
country_subdivisions <- tt$country_subdivisions |> clean_names()
former_countries     <- tt$former_countries |> clean_names()

tidytuesdayR::readme(tt)
rm(tt)
```

3. Examine the Data

Show code
```{r}
#| label: examine
#| include: true
#| eval: true
#| results: 'hide'
#| warning: false

glimpse(countries)
glimpse(country_subdivisions)
glimpse(former_countries)
```

4. Tidy Data

Show code
```{r}
#| label: tidy
#| warning: false

### |- tidy data ----

### |- ridge data ----
ridge_data <- countries |>
  mutate(
    first_letter = substr(alpha_2, 1, 1),
    first_letter = factor(first_letter, levels = rev(sort(unique(first_letter))))
  )

### |- waffle data ----
waffle_data <- countries |>
  summarise(
    `Complete System` = sum(!is.na(alpha_2) & !is.na(alpha_3) & !is.na(numeric)),
    `Partial System` = n() - sum(!is.na(alpha_2) & !is.na(alpha_3) & !is.na(numeric))
  ) |>
  pivot_longer(
    cols = everything(),
    names_to = "key",
    values_to = "value"
  ) |>
  mutate(
    value = value / 10,
    key = factor(key, levels = c("Complete System", "Partial System"))
  )
```

5. Visualization Parameters

Show code
```{r}
#| label: params
#| include: true
#| warning: false

### |- plot aesthetics ----
bkg_col      <- "#f5f5f2"
title_col    <- "gray20"
subtitle_col <- "gray20"
caption_col  <- "gray30"
text_col     <- "gray30"
col_palette  <- viridis::rocket(5)

### |-  titles and caption ----
# icons
tt <- str_glue("#TidyTuesday: { 2024 } Week { 46 } &bull; Source: ISOcodes R Package<br>")
li <- str_glue("<span style='font-family:fa6-brands'>&#xf08c;</span>")
gh <- str_glue("<span style='font-family:fa6-brands'>&#xf09b;</span>")
bs <- str_glue("<span style='font-family:fa6-brands'>&#xe671; </span>")

# text
caption_text <- str_glue("{tt} {li} stevenponce &bull; {bs} sponce1 &bull; {gh} poncest &bull; #rstats #ggplot2")

### |-  fonts ----
font_add("fa6-brands", here::here("fonts/6.6.0/Font Awesome 6 Brands-Regular-400.otf"))
font_add_google("Oswald", regular.wt = 400, family = "title")
font_add_google("Source Sans Pro", family = "text")
font_add_google("Roboto Mono", family = "numbers")
font_add_google("Noto Sans", regular.wt = 400, family = "caption")
showtext_auto(enable = TRUE)

### |-  plot theme ----
theme_set(theme_minimal(base_size = 14, base_family = "text"))                

theme_update(
    plot.title.position   = "plot",
    plot.caption.position = "plot",
    legend.position       = "plot",
    plot.background       = element_rect(fill = bkg_col, color = bkg_col),
    panel.background      = element_rect(fill = bkg_col, color = bkg_col),
    plot.margin           = margin(t = 5, r = 15, b = 5, l = 15),
    panel.spacing         = unit(1, "lines"),
    axis.title.x          = element_text(margin = margin(10, 0, 0, 0), 
                                         size = rel(1),
                                         color = text_col,
                                         family = "text",
                                         face = "bold"),
    axis.title.y          = element_text(margin = margin(0, 10, 0, 0),
                                         size = rel(1),
                                         color = text_col,
                                         family = "text",
                                         face = "bold"),
    axis.text             = element_text(size = rel(0.8),
                                         color = text_col,
                                         family = "text"),
    panel.grid.minor      = element_blank(),
    panel.grid.major      = element_line(color = "gray95", linewidth = 0.2),
    panel.grid.major.y    = element_blank()
)
```

6. Plot

Show code
```{r}
#| label: plot
#| warning: false

### |- ridge plot ----
ridge_plot <- ridge_data |>
  ggplot(aes(x = numeric, y = first_letter, fill = after_stat(x))) +

  # Geoms
  # add reference lines
  geom_vline(
    xintercept = seq(0, 1000, 200),
    color = "gray90",
    linetype = "dashed"
  ) +
  # ridges
  geom_density_ridges_gradient(
    alpha = 0.8,
    scale = 0.95,
    rel_min_height = 0.005,
    bandwidth = 25,
    color = text_col,
    show.legend = TRUE
  ) +
  # country positions
  geom_point(
    data = ridge_data,
    aes(x = numeric, y = first_letter),
    size = 0.8,
    alpha = 0.3,
    color = text_col
  ) +
  # annotations
  annotate(
    "text",
    x = 10,
    y = "E",
    label = "Early alphabet countries\noften have lower codes",
    size = 3.0,
    family = "text",
    color = "gray25",
    lineheight = 0.9,
    hjust = 0.4
  ) +
  annotate(
    "text",
    x = 850,
    y = "W",
    label = "Higher codes cluster in\nlater alphabet regions",
    size = 3.0,
    family = "text",
    color = "gray25",
    lineheight = 0.9,
    vjust = 0.5
  ) +

  # Scales
  scale_x_continuous(
    breaks = seq(0, 1000, 200),
    expand = c(0.02, 0)
  ) +
  scale_y_discrete() +
  scale_fill_gradientn(
    colors = col_palette,
    name = "Numeric Code Range",
    guide = guide_colorbar(
      title.position = "top",
      barwidth = unit(15, "lines"),
      barheight = unit(0.5, "lines")
    )
  ) +
  coord_cartesian(clip = "off") +

  # Labs
  labs(
    x = "Numeric Country Code (0-999)",
    y = "First Letter of Alpha-2 Code"
  ) +

  # Theme
  theme(
    legend.position = "top",
    legend.justification = "right",
    legend.direction = "horizontal",
    legend.title = element_text(size = rel(0.8)),
    legend.text = element_text(size = rel(0.7)),
    legend.key.width = unit(2.2, "cm"),
    legend.key.height = unit(0.3, "cm"),
    legend.spacing.x = unit(0.2, "cm"),
    plot.margin = margin(-5, 30, 5, 30),
    panel.spacing = unit(2, "lines")
  )

### |- waffle plot ----
waffle_plot <- waffle_data |>
  ggplot(aes(fill = key, values = value)) +

  # Geom
  geom_waffle(
    n_rows = 5,
    size = 0.5,
    colour = "white",
    flip = TRUE,
    radius = unit(2, "pt")
  ) +
  # Scales
  scale_fill_manual(values = col_palette[c(1, 5)]) +
  coord_equal(ratio = 1) +

  # Theme
  theme_void() +
  theme(
    legend.position = "bottom",
    legend.title = element_blank(),
    legend.text = element_text(size = rel(1)),
    plot.margin = margin(10, 5, 0, 5),
    plot.background = element_rect(fill = bkg_col, color = bkg_col),
    panel.background = element_rect(fill = bkg_col, color = bkg_col),
  )

### |- title plot ----

# Add total count annotation
n_countries <- nrow(countries)

title_plot <- ggplot() +
  # Geoms
  annotate(
    "text",
    x = 0, y = 0.85,
    label = "The Architecture of\nGlobal Country Codes",
    hjust = 0,
    size = 10,
    lineheight = 1,
    fontface = "bold",
    family = "title",
    color = title_col
  ) +
  annotate(
    "text",
    x = 0, y = 0.5,
    label = str_wrap(
      "Analysis of ISO country codes reveals geographic and alphabetic patterns
      in international standardization. Most nations maintain three distinct identifiers.",
      width = 65
    ),
    hjust = 0,
    size = 3.5,
    color = title_col,
    family = "text"
  ) +
  annotate(
    "text",
    x = 0, y = 0.3,
    label = glue("Analysis of {n_countries} country codes"),
    hjust = 0,
    size = 3.5,
    family = "text",
    color = title_col
  ) +
  annotate("text",
    x = 0, y = 0.1,
    label = "Example:\nUS (Alpha-2)\nUSA (Alpha-3)\n840 (Numeric)",
    hjust = 0,
    size = 2.8,
    color = title_col,
    family = "text",
    lineheight = 1.2
  ) +

  # Scales
  scale_x_continuous(limits = c(0, 1)) +
  scale_y_continuous(limits = c(0, 1)) +

  # Them
  theme_void() +
  theme(
    plot.background = element_rect(fill = bkg_col, color = bkg_col),
    panel.background = element_rect(fill = bkg_col, color = bkg_col),
    plot.margin = margin(5, 10, 0, 10)
  )

### |- explanatory text plot for the waffle chart ----
waffle_explanation <- ggplot() +

  # Geoms
  annotate("text",
    x = 0, y = 0.85,
    label = "Country Code Systems\n",
    hjust = 0, size = 3.5, fontface = "bold", family = "text"
  ) +
  annotate("text",
    x = 0, y = 0.55,
    label = str_wrap("Each square represents 10 countries. A complete system means a country has
                     all three standardized codes shown in the ridge plot below: Alpha-2 (e.g., US),
                     Alpha-3 (USA), and Numeric (840).", 55),
    hjust = 0, size = 2.8, color = title_col, family = "text"
  ) +

  # Scales
  scale_x_continuous(limits = c(0, 1)) +
  scale_y_continuous(limits = c(0, 1)) +

  # Theme
  theme_void() +
  theme(
    plot.background = element_rect(fill = bkg_col, color = bkg_col),
    panel.background = element_rect(fill = bkg_col, color = bkg_col),
    plot.margin = margin(5, 10, 0, 10)
  )

### |- combined plot ----

# define layout design
design <- c(
  area(1, 1, 2, 4), # title_plot
  area(1, 5, 1, 6), # waffle_plot
  area(2, 5, 2, 6), # waffle_explanation
  area(3, 1, 5, 6) # ridge_plot
)

combined_plot <- title_plot + waffle_plot + waffle_explanation + ridge_plot +
  plot_layout(
    design = design,
    heights = c(1.2, 1, 2, 1, 1), # Simplified heights
    widths = c(1, 1, -0.4, 1, 0.9, 0.9) # Slightly wider right side
  ) +
  plot_annotation(
    caption = caption_text,
    theme = theme(
      plot.background  = element_rect(fill = bkg_col, color = bkg_col),
      panel.background = element_rect(fill = bkg_col, color = bkg_col),
      plot.margin  = margin(10, 10, 10, 10),
      plot.caption = element_markdown(
        size       = rel(0.60),
        family     = "caption",
        color      = alpha(caption_col, 0.9),
        lineheight = 0.65,
        hjust      = 0.5,
        margin     = margin(t = 10, b = 5)
      )
    )
  )
```

7. Save

Show code
```{r}
#| label: save
#| warning: false

### |-  plot image ----

library(ggplotify)
library(grid)

# Convert patchwork plot to grob
# There was some issues between patchwork and ggsave
plot_grob <- as.grob(combined_plot)

# Activate showtext manually
showtext_begin()
showtext_opts(dpi = 320, regular.wt = 300, bold.wt = 800)

# Save the plot as PNG
invisible({
  png(
    filename = here::here("data_visualizations/TidyTuesday/2024/tt_2024_46.png"),
    width = 10, height = 12, units = "in", res = 320
  )
  grid.draw(plot_grob)
  dev.off()
})

# Deactivate showtext
showtext_end()

### |-  plot thumbnail----
magick::image_read(here::here("data_visualizations/TidyTuesday/2024/tt_2024_46.png")) |>
  magick::image_resize(geometry = "400") |>
  magick::image_write(here::here("data_visualizations/TidyTuesday/2024/thumbnails/tt_2024_46.png"))
```

8. Session Info

Expand for Session Info
R version 4.4.1 (2024-06-14 ucrt)
Platform: x86_64-w64-mingw32/x64
Running under: Windows 11 x64 (build 22631)

Matrix products: default


locale:
[1] LC_COLLATE=English_United States.utf8 
[2] LC_CTYPE=English_United States.utf8   
[3] LC_MONETARY=English_United States.utf8
[4] LC_NUMERIC=C                          
[5] LC_TIME=English_United States.utf8    

time zone: America/New_York
tzcode source: internal

attached base packages:
[1] grid      stats     graphics  grDevices datasets  utils     methods  
[8] base     

other attached packages:
 [1] ggplotify_0.1.2 patchwork_1.3.0 waffle_1.0.2    ggridges_0.5.6 
 [5] here_1.0.1      glue_1.8.0      scales_1.3.0    janitor_2.2.0  
 [9] showtext_0.9-7  showtextdb_3.0  sysfonts_0.8.9  ggtext_0.1.2   
[13] lubridate_1.9.3 forcats_1.0.0   stringr_1.5.1   dplyr_1.1.4    
[17] purrr_1.0.2     readr_2.1.5     tidyr_1.3.1     tibble_3.2.1   
[21] ggplot2_3.5.1   tidyverse_2.0.0 pacman_0.5.1   

loaded via a namespace (and not attached):
 [1] tidyselect_1.2.1   viridisLite_0.4.2  farver_2.1.2       viridis_0.6.5     
 [5] fastmap_1.2.0      gh_1.4.1           digest_0.6.37      timechange_0.3.0  
 [9] lifecycle_1.0.4    rsvg_2.6.1         magrittr_2.0.3     compiler_4.4.0    
[13] rlang_1.1.6        tools_4.4.0        utf8_1.2.4         yaml_2.3.10       
[17] knitr_1.49         labeling_0.4.3     htmlwidgets_1.6.4  bit_4.5.0         
[21] curl_6.0.0         plyr_1.8.9         xml2_1.3.6         camcorder_0.1.0   
[25] RColorBrewer_1.1-3 tidytuesdayR_1.1.2 withr_3.0.2        fansi_1.0.6       
[29] colorspace_2.1-1   extrafontdb_1.0    gitcreds_0.1.2     cli_3.6.4         
[33] rmarkdown_2.29     crayon_1.5.3       generics_0.1.3     rstudioapi_0.17.1 
[37] tzdb_0.5.0         commonmark_1.9.2   parallel_4.4.0     yulab.utils_0.1.8 
[41] vctrs_0.6.5        jsonlite_1.8.9     gridGraphics_0.5-1 hms_1.1.3         
[45] bit64_4.5.2        systemfonts_1.1.0  magick_2.8.5       gifski_1.32.0-1   
[49] codetools_0.2-20   DT_0.33            stringi_1.8.4      gtable_0.3.6      
[53] extrafont_0.19     munsell_0.5.1      pillar_1.9.0       rappdirs_0.3.3    
[57] htmltools_0.5.8.1  R6_2.5.1           httr2_1.0.6        rprojroot_2.0.4   
[61] vroom_1.6.5        evaluate_1.0.1     markdown_1.13      gridtext_0.1.5    
[65] snakecase_0.11.1   renv_1.0.3         Rcpp_1.0.13-1      svglite_2.1.3     
[69] gridExtra_2.3      Rttf2pt1_1.3.12    xfun_0.49          fs_1.6.5          
[73] pkgconfig_2.0.3   

9. GitHub Repository

Expand for GitHub Repo

Access the GitHub repository here

Back to top
Source Code
---
title: "The Architecture of Global Country Codes"
subtitle: "Analysis of ISO country codes reveals geographic and alphabetic patterns
      in international standardization. Most nations maintain three distinct identifiers."
author: "Steven Ponce"
date: "2024-11-09"
categories: ["TidyTuesday", "Data Visualization", "R Programming", "2024"]
image: "thumbnails/tt_2024_46.png"

format:
  html:
    toc: true
    toc-depth: 5
    code-link: true
    code-fold: true
    code-tools: true
    code-summary: "Show code"
    self-contained: true

editor_options: 
  chunk_output_type: inline
  
execute: 
  error: false
  message: false
  warning: false
  eval: true

# share:
#   permalink: "https://stevenponce.netlify.app/data_visualizations.png"
#   linkedin: true
#   twitter: true
#   email: true
---

![A visualization titled 'The Architecture of Global Country Codes' showing an analysis of 249 ISO country codes by first letter and numeric value. Ridge plots in purple to orange show the distribution of country codes, with early alphabet countries having lower numeric codes and later alphabet countries having higher codes. A waffle chart in the top right indicates which countries maintain complete sets of Alpha-2, Alpha-3, and Numeric codes.](tt_2024_46.png){#fig-1}


### <mark> __Steps to Create this Graphic__ </mark>

#### 1. Load Packages & Setup 

```{r}
#| label: load
#| warning: false

## 1. LOAD PACKAGES & SETUP ----
if (!require("pacman")) install.packages("pacman")
pacman::p_load(
  tidyverse, # Easily Install and Load the 'Tidyverse'
  ggtext, # Improved Text Rendering Support for 'ggplot2'
  showtext, # Using Fonts More Easily in R Graphs
  janitor, # Simple Tools for Examining and Cleaning Dirty Data
  scales, # Scale Functions for Visualization
  glue, # Interpreted String Literals
  here, # A Simpler Way to Find Your Files
  ggridges, # Ridgeline Plots in 'ggplot2'
  waffle, # Create Waffle Chart Visualizations
  patchwork # The Composer of Plots
)

### |- figure size ----
camcorder::gg_record(
  dir    = here::here("temp_plots"),
  device = "png",
  width  =  10,
  height =  12,
  units  = "in",
  dpi    = 320
)

### |- resolution ----
showtext_opts(dpi = 320, regular.wt = 300, bold.wt = 800)
```

#### 2. Read in the Data 

```{r}
#| label: read
#| include: true
#| eval: true
#| warning: false

tt <- tidytuesdayR::tt_load(2024, week = 46)

countries            <- tt$countries |> clean_names()
country_subdivisions <- tt$country_subdivisions |> clean_names()
former_countries     <- tt$former_countries |> clean_names()

tidytuesdayR::readme(tt)
rm(tt)
```

#### 3. Examine the Data

```{r}
#| label: examine
#| include: true
#| eval: true
#| results: 'hide'
#| warning: false

glimpse(countries)
glimpse(country_subdivisions)
glimpse(former_countries)
```

#### 4. Tidy Data 

```{r}
#| label: tidy
#| warning: false

### |- tidy data ----

### |- ridge data ----
ridge_data <- countries |>
  mutate(
    first_letter = substr(alpha_2, 1, 1),
    first_letter = factor(first_letter, levels = rev(sort(unique(first_letter))))
  )

### |- waffle data ----
waffle_data <- countries |>
  summarise(
    `Complete System` = sum(!is.na(alpha_2) & !is.na(alpha_3) & !is.na(numeric)),
    `Partial System` = n() - sum(!is.na(alpha_2) & !is.na(alpha_3) & !is.na(numeric))
  ) |>
  pivot_longer(
    cols = everything(),
    names_to = "key",
    values_to = "value"
  ) |>
  mutate(
    value = value / 10,
    key = factor(key, levels = c("Complete System", "Partial System"))
  )
```


#### 5. Visualization Parameters 

```{r}
#| label: params
#| include: true
#| warning: false

### |- plot aesthetics ----
bkg_col      <- "#f5f5f2"
title_col    <- "gray20"
subtitle_col <- "gray20"
caption_col  <- "gray30"
text_col     <- "gray30"
col_palette  <- viridis::rocket(5)

### |-  titles and caption ----
# icons
tt <- str_glue("#TidyTuesday: { 2024 } Week { 46 } &bull; Source: ISOcodes R Package<br>")
li <- str_glue("<span style='font-family:fa6-brands'>&#xf08c;</span>")
gh <- str_glue("<span style='font-family:fa6-brands'>&#xf09b;</span>")
bs <- str_glue("<span style='font-family:fa6-brands'>&#xe671; </span>")

# text
caption_text <- str_glue("{tt} {li} stevenponce &bull; {bs} sponce1 &bull; {gh} poncest &bull; #rstats #ggplot2")

### |-  fonts ----
font_add("fa6-brands", here::here("fonts/6.6.0/Font Awesome 6 Brands-Regular-400.otf"))
font_add_google("Oswald", regular.wt = 400, family = "title")
font_add_google("Source Sans Pro", family = "text")
font_add_google("Roboto Mono", family = "numbers")
font_add_google("Noto Sans", regular.wt = 400, family = "caption")
showtext_auto(enable = TRUE)

### |-  plot theme ----
theme_set(theme_minimal(base_size = 14, base_family = "text"))                

theme_update(
    plot.title.position   = "plot",
    plot.caption.position = "plot",
    legend.position       = "plot",
    plot.background       = element_rect(fill = bkg_col, color = bkg_col),
    panel.background      = element_rect(fill = bkg_col, color = bkg_col),
    plot.margin           = margin(t = 5, r = 15, b = 5, l = 15),
    panel.spacing         = unit(1, "lines"),
    axis.title.x          = element_text(margin = margin(10, 0, 0, 0), 
                                         size = rel(1),
                                         color = text_col,
                                         family = "text",
                                         face = "bold"),
    axis.title.y          = element_text(margin = margin(0, 10, 0, 0),
                                         size = rel(1),
                                         color = text_col,
                                         family = "text",
                                         face = "bold"),
    axis.text             = element_text(size = rel(0.8),
                                         color = text_col,
                                         family = "text"),
    panel.grid.minor      = element_blank(),
    panel.grid.major      = element_line(color = "gray95", linewidth = 0.2),
    panel.grid.major.y    = element_blank()
)
```


#### 6. Plot 

```{r}
#| label: plot
#| warning: false

### |- ridge plot ----
ridge_plot <- ridge_data |>
  ggplot(aes(x = numeric, y = first_letter, fill = after_stat(x))) +

  # Geoms
  # add reference lines
  geom_vline(
    xintercept = seq(0, 1000, 200),
    color = "gray90",
    linetype = "dashed"
  ) +
  # ridges
  geom_density_ridges_gradient(
    alpha = 0.8,
    scale = 0.95,
    rel_min_height = 0.005,
    bandwidth = 25,
    color = text_col,
    show.legend = TRUE
  ) +
  # country positions
  geom_point(
    data = ridge_data,
    aes(x = numeric, y = first_letter),
    size = 0.8,
    alpha = 0.3,
    color = text_col
  ) +
  # annotations
  annotate(
    "text",
    x = 10,
    y = "E",
    label = "Early alphabet countries\noften have lower codes",
    size = 3.0,
    family = "text",
    color = "gray25",
    lineheight = 0.9,
    hjust = 0.4
  ) +
  annotate(
    "text",
    x = 850,
    y = "W",
    label = "Higher codes cluster in\nlater alphabet regions",
    size = 3.0,
    family = "text",
    color = "gray25",
    lineheight = 0.9,
    vjust = 0.5
  ) +

  # Scales
  scale_x_continuous(
    breaks = seq(0, 1000, 200),
    expand = c(0.02, 0)
  ) +
  scale_y_discrete() +
  scale_fill_gradientn(
    colors = col_palette,
    name = "Numeric Code Range",
    guide = guide_colorbar(
      title.position = "top",
      barwidth = unit(15, "lines"),
      barheight = unit(0.5, "lines")
    )
  ) +
  coord_cartesian(clip = "off") +

  # Labs
  labs(
    x = "Numeric Country Code (0-999)",
    y = "First Letter of Alpha-2 Code"
  ) +

  # Theme
  theme(
    legend.position = "top",
    legend.justification = "right",
    legend.direction = "horizontal",
    legend.title = element_text(size = rel(0.8)),
    legend.text = element_text(size = rel(0.7)),
    legend.key.width = unit(2.2, "cm"),
    legend.key.height = unit(0.3, "cm"),
    legend.spacing.x = unit(0.2, "cm"),
    plot.margin = margin(-5, 30, 5, 30),
    panel.spacing = unit(2, "lines")
  )

### |- waffle plot ----
waffle_plot <- waffle_data |>
  ggplot(aes(fill = key, values = value)) +

  # Geom
  geom_waffle(
    n_rows = 5,
    size = 0.5,
    colour = "white",
    flip = TRUE,
    radius = unit(2, "pt")
  ) +
  # Scales
  scale_fill_manual(values = col_palette[c(1, 5)]) +
  coord_equal(ratio = 1) +

  # Theme
  theme_void() +
  theme(
    legend.position = "bottom",
    legend.title = element_blank(),
    legend.text = element_text(size = rel(1)),
    plot.margin = margin(10, 5, 0, 5),
    plot.background = element_rect(fill = bkg_col, color = bkg_col),
    panel.background = element_rect(fill = bkg_col, color = bkg_col),
  )

### |- title plot ----

# Add total count annotation
n_countries <- nrow(countries)

title_plot <- ggplot() +
  # Geoms
  annotate(
    "text",
    x = 0, y = 0.85,
    label = "The Architecture of\nGlobal Country Codes",
    hjust = 0,
    size = 10,
    lineheight = 1,
    fontface = "bold",
    family = "title",
    color = title_col
  ) +
  annotate(
    "text",
    x = 0, y = 0.5,
    label = str_wrap(
      "Analysis of ISO country codes reveals geographic and alphabetic patterns
      in international standardization. Most nations maintain three distinct identifiers.",
      width = 65
    ),
    hjust = 0,
    size = 3.5,
    color = title_col,
    family = "text"
  ) +
  annotate(
    "text",
    x = 0, y = 0.3,
    label = glue("Analysis of {n_countries} country codes"),
    hjust = 0,
    size = 3.5,
    family = "text",
    color = title_col
  ) +
  annotate("text",
    x = 0, y = 0.1,
    label = "Example:\nUS (Alpha-2)\nUSA (Alpha-3)\n840 (Numeric)",
    hjust = 0,
    size = 2.8,
    color = title_col,
    family = "text",
    lineheight = 1.2
  ) +

  # Scales
  scale_x_continuous(limits = c(0, 1)) +
  scale_y_continuous(limits = c(0, 1)) +

  # Them
  theme_void() +
  theme(
    plot.background = element_rect(fill = bkg_col, color = bkg_col),
    panel.background = element_rect(fill = bkg_col, color = bkg_col),
    plot.margin = margin(5, 10, 0, 10)
  )

### |- explanatory text plot for the waffle chart ----
waffle_explanation <- ggplot() +

  # Geoms
  annotate("text",
    x = 0, y = 0.85,
    label = "Country Code Systems\n",
    hjust = 0, size = 3.5, fontface = "bold", family = "text"
  ) +
  annotate("text",
    x = 0, y = 0.55,
    label = str_wrap("Each square represents 10 countries. A complete system means a country has
                     all three standardized codes shown in the ridge plot below: Alpha-2 (e.g., US),
                     Alpha-3 (USA), and Numeric (840).", 55),
    hjust = 0, size = 2.8, color = title_col, family = "text"
  ) +

  # Scales
  scale_x_continuous(limits = c(0, 1)) +
  scale_y_continuous(limits = c(0, 1)) +

  # Theme
  theme_void() +
  theme(
    plot.background = element_rect(fill = bkg_col, color = bkg_col),
    panel.background = element_rect(fill = bkg_col, color = bkg_col),
    plot.margin = margin(5, 10, 0, 10)
  )

### |- combined plot ----

# define layout design
design <- c(
  area(1, 1, 2, 4), # title_plot
  area(1, 5, 1, 6), # waffle_plot
  area(2, 5, 2, 6), # waffle_explanation
  area(3, 1, 5, 6) # ridge_plot
)

combined_plot <- title_plot + waffle_plot + waffle_explanation + ridge_plot +
  plot_layout(
    design = design,
    heights = c(1.2, 1, 2, 1, 1), # Simplified heights
    widths = c(1, 1, -0.4, 1, 0.9, 0.9) # Slightly wider right side
  ) +
  plot_annotation(
    caption = caption_text,
    theme = theme(
      plot.background  = element_rect(fill = bkg_col, color = bkg_col),
      panel.background = element_rect(fill = bkg_col, color = bkg_col),
      plot.margin  = margin(10, 10, 10, 10),
      plot.caption = element_markdown(
        size       = rel(0.60),
        family     = "caption",
        color      = alpha(caption_col, 0.9),
        lineheight = 0.65,
        hjust      = 0.5,
        margin     = margin(t = 10, b = 5)
      )
    )
  )
```



#### 7. Save

```{r}
#| label: save
#| warning: false

### |-  plot image ----

library(ggplotify)
library(grid)

# Convert patchwork plot to grob
# There was some issues between patchwork and ggsave
plot_grob <- as.grob(combined_plot)

# Activate showtext manually
showtext_begin()
showtext_opts(dpi = 320, regular.wt = 300, bold.wt = 800)

# Save the plot as PNG
invisible({
  png(
    filename = here::here("data_visualizations/TidyTuesday/2024/tt_2024_46.png"),
    width = 10, height = 12, units = "in", res = 320
  )
  grid.draw(plot_grob)
  dev.off()
})

# Deactivate showtext
showtext_end()

### |-  plot thumbnail----
magick::image_read(here::here("data_visualizations/TidyTuesday/2024/tt_2024_46.png")) |>
  magick::image_resize(geometry = "400") |>
  magick::image_write(here::here("data_visualizations/TidyTuesday/2024/thumbnails/tt_2024_46.png"))
```



#### 8. Session Info

::: {.callout-tip collapse="true"}
##### Expand for Session Info

```{r, echo = FALSE}
#| eval: true
#| warning: false

sessionInfo()
```
:::

#### 9. GitHub Repository

::: {.callout-tip collapse="true"}

##### Expand for GitHub Repo
 
[Access the GitHub repository here](https://github.com/poncest/personal-website/)
:::

© 2024 Steven Ponce

Source Issues